/*
 ===============================================================================
 Name        : main.cpp
 Author      : $(user)
 Version     : 1.0.0
 Date		 : $(date)
 Copyright   :
 License	 : CC BY-SA 3.0
 Description :
 ===============================================================================
  	 	 	 	 	 	 	 	 History
 ---------+---------+--------------------------------------------+-------------
 DATE     |	VERSION |	DESCRIPTIONS							 |	By
 ---------+---------+--------------------------------------------+-------------

 ===============================================================================
 */
#include "driver_config.h"
#ifdef __USE_CMSIS
#include "LPC12xx.h"
#endif

#include <cr_section_macros.h>
#include <NXP/crp.h>

// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

// TODO: insert other include files here
#include "lpc12xx_sysctrl.h"
#include "lpc12xx_iocon.h"
#include "lpc12xx_gpio.h"
#include "lpc12xx_timer16.h"

// LPCXpresso processor card LED
#define LED_PORT 	LPC_GPIO0		// Port for led
#define LED_BIT 	7				// Bit on port for led
#define LED_ON 		1				// Level to set port to turn on led
#define LED_OFF 	0				// Level to set port to turn off led

//
// Private Variables
//
TIM16_InitTypeDef TIM16_InitStruct;
TIM16_MATCHTypeDef TIM16_MatchConfigStruct ;
IOCON_PIO_CFG_Type PIO_ConfigStructure;
volatile uint32_t timer16_0_counter;

//
// 16 bits timer interrupt handler
//
void TIMER16_0_IRQHandler() {
    uint32_t  int_status_reg;

    int_status_reg = TIM16_GetIntStatusReg (LPC_CT16B0);

    /*clear the interrupt flag of match channel 0 */
    if (int_status_reg & TIM16_INT_MR0)
    {
    	TIM16_ClearIntPendingBit(LPC_CT16B0, TIM16_INT_MR0);
    	timer16_0_counter++;
    }
}

void timer16_init() {
    /* Timer16B0 I/O config: match channel 0 on location0 (PIO0_11) */
    IOCON_StructInit (&PIO_ConfigStructure);
    PIO_ConfigStructure.type = IOCON_CT16_B0_MAT0_LOC0;
    IOCON_SetFunc (&PIO_ConfigStructure);


    /* Initialize timer16B0, prescale count time of 100uS */
    TIM16_InitStruct.PrescaleOption = TIM16_PRESCALE_USVAL;
    TIM16_InitStruct.PrescaleValue = 100;

    /* Match channel 0, MR0 */
    TIM16_MatchConfigStruct.MatchChannel = TIM16_MATCH_CHANNEL0;
    /* Enable interrupt when MR0 matches the value in TC register */
    TIM16_MatchConfigStruct.IntOnMatch   = TRUE;
    /* Enable reset on MR0: TIMER will reset if MR0 matches it */
    TIM16_MatchConfigStruct.ResetOnMatch = TRUE;
    /* No Stop on MR0 if MR0 matches it */
    TIM16_MatchConfigStruct.StopOnMatch  = FALSE;
    /* Toggle MR0 pin if MR0 matches it */
    TIM16_MatchConfigStruct.ExtMatchOutputType =TIM16_EXTMATCH_TOGGLE;
    /* Set Match value, count value of 1000 (1000 * 100uS = 1mS --> 1KHz) */
    TIM16_MatchConfigStruct.MatchValue   = 10;

    /* Set configuration for Tim16_config and Tim16_MatchConfig */
    TIM16_Init(LPC_CT16B0, TIM16_TIMER_MODE,&TIM16_InitStruct);
    TIM16_ConfigMatch(LPC_CT16B0,&TIM16_MatchConfigStruct);

    /* preemption = 1, sub-priority = 1 */
    NVIC_SetPriority(TIMER_16_0_IRQn, ((0x01<<3)|0x01));
    /* Enable interrupt for timer */
    NVIC_EnableIRQ(TIMER_16_0_IRQn);
    /* To start timer16B0 */
    TIM16_Cmd(LPC_CT16B0, ENABLE);
}

int main(void) {

	// set GPIO
	IOCON_PIO_CFG_Type PIO_mode;
	SYS_ConfigAHBCLK(SYS_AHBCLKCTRL_GPIO0, ENABLE);
	IOCON_StructInit(&PIO_mode);
	PIO_mode.type = IOCON_PIO_0_7;
	IOCON_SetFunc(&PIO_mode);
	GPIO_SetDir(LED_PORT, LED_BIT, 1);

	timer16_0_counter = 0;
	
	// Initialise Timer16_0
	timer16_init();

	// Enter an infinite loop, just incrementing a counter
	volatile uint32_t i = timer16_0_counter ;
	while(1) {
		if ( (timer16_0_counter-i)>500 ) {
			GPIO_SetInvert(LED_PORT, LED_BIT, 1);
			i = timer16_0_counter;
		}
	}
	return 0 ;
}

//
// FreeRTOS Hook Functions
//
void vApplicationIdleHook() {
	// TODO: FreeRTOS Idle Hook
}

void vApplicationTickHook() {
	// TODO: FreeRTOS Tick Hook
}

void vApplicationMallocFailedHook() {
	// TODO: Faile malloc Hook
}
